/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package autenticacionmodulo;

import java.io.IOException;
import java.io.StringWriter;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.objectweb.jonas.security.auth.JGroup;
import org.objectweb.jonas.security.auth.JPrincipal;
import org.objectweb.jonas.security.auth.JRole;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 *
 * @author Larry
 */
public class LoginModuleEspol implements LoginModule {

    private Subject subject;
    private CallbackHandler callbackHandler;
    private Map<String, ?> options;
    private String principalName;
    private ArrayList principalRoles;
    private boolean loginWasDoneWithSuccess = false;
    private String password;

    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.options = options;

        System.out.println("LoginModuleEspol: initialize ->");
        System.out.println("this.subject: " + subject);
        Set<Principal> a = subject.getPrincipals();
        for (Principal principal : a) {
            System.out.println("Principal: " + principal.toString());
        }
    }

    public boolean login() throws LoginException {
        System.out.println("LoginModuleEspol: login()");
        if (callbackHandler == null) {
            throw new LoginException("No se especificó callbackHandler");
        }


// Handle callbacks
        NameCallback nameCallback = new NameCallback("Usuario :");
// False to hide password when it is entered
        PasswordCallback passwordCallback = new PasswordCallback("Contraseña :", false);
        Callback[] callbacks = null;
        callbacks = new Callback[]{nameCallback, passwordCallback};
        boolean seAutentico = false;
        try {
            callbackHandler.handle(callbacks);

// Obtener los valores
            principalName = nameCallback.getName();
            if (principalName == null) {
                throw new LoginException("A null username is not a valid username");
            }

            char[] arrayPass = passwordCallback.getPassword();
            if (arrayPass == null) {
                throw new LoginException("A null password is not a valid password");
            }
            password = new String(arrayPass);
            System.out.println("principalName: " + principalName);
            System.out.println("password: " + password);

            //Invocacion al WebService
            try {
                Node nodo;
                // Call Web Service Operation
                ec.edu.espol.academico.webservices.DirectorioEspol service = new ec.edu.espol.academico.webservices.DirectorioEspol();
                ec.edu.espol.academico.webservices.DirectorioEspolSoap port = service.getDirectorioEspolSoap12();
                // TODO initialize WS operation arguments here
                java.lang.String varUser = "lbeltran";
                java.lang.String varContrasenia = "200211324";
                // TODO process result here
                ec.edu.espol.academico.webservices.DatosUsuarioResponse.DatosUsuarioResult result = port.datosUsuario(varUser, varContrasenia);
                nodo = (Node) result.getAny();

                CargadorXml cargador = new CargadorXml();
                NewDataSet obj = cargador.getNewDataSet(nodeToString(nodo.getFirstChild()));
                System.out.println("obj: " + obj.getClass());
                System.out.println("Now I see it");

                System.out.println("Apellidos: " + obj.getDatosUsuario().getApellidos());
                System.out.println("Nombres:  " + obj.getDatosUsuario().getNombres());
                System.out.println("Matricula: " + obj.getDatosUsuario().getMatricula());
                System.out.println("Cedula: " + obj.getDatosUsuario().getCedula());


//                InitialContext ic;
//                ic = new InitialContext();
//                AutenticadorRemote autenticador = (AutenticadorRemote) ic.lookup("solicitudesfiec.autenticacion.AutenticadorRemote");
//                seAutentico = autenticador.autenticarEspol(principalName, arrayPass);
            } catch (TransformerException ex) {
                Logger.getLogger(LoginModuleEspol.class.getName()).log(Level.SEVERE, null, ex);
                throw createChainedLoginException("Parece ser que el xml no es valido", ex);
            } 

            principalRoles = new ArrayList();
            if (seAutentico) {
                loginWasDoneWithSuccess = true;
            }
        } catch (IOException iOException) {
            System.out.println("Un problema de entrada / salida");
            iOException.printStackTrace();
        } catch (UnsupportedCallbackException unsupportedCallbackException) {
            unsupportedCallbackException.printStackTrace();
        }
        System.out.println("loginWasDoneWithSuccess: " + loginWasDoneWithSuccess);
        return loginWasDoneWithSuccess;
    }

    public boolean commit() throws LoginException {
        System.out.println("LoginModuleEspol: commit()");
        return loginWasDoneWithSuccess;
    }

    public boolean abort() throws LoginException {
        System.out.println("LoginModuleEspol: abort()");
        //overall authentication succeeded
        if (loginWasDoneWithSuccess) {
            // Reset temp values
            principalName = null;
            principalRoles = null;
        }
        return loginWasDoneWithSuccess;
    }

    public boolean logout() throws LoginException {
        System.out.println("LoginModuleEspol: logout()");
        //overall authentication succeeded
        if (loginWasDoneWithSuccess) {
            // Remove principal name
            subject.getPrincipals().remove(new JPrincipal(principalName));
        }
        return loginWasDoneWithSuccess;
    }

    public static String nodeToString(Node ele) throws TransformerException {
// Set up the output transformer
        TransformerFactory transfac = TransformerFactory.newInstance();
        Transformer trans = transfac.newTransformer();
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        trans.setOutputProperty(OutputKeys.INDENT, "yes");

// Print the DOM node
        StringWriter sw = new StringWriter();
        StreamResult result2 = new StreamResult(sw);
        DOMSource source = new DOMSource(ele);
        trans.transform(source, result2);
        String xmlString = sw.toString();
        return xmlString;
    }

    /**
     * Create a LoginException with the given message and set the cause to the given Exception
     * @param msg Exception message
     * @param e Root cause
     * @return LoginException the chained LoginException
     */
    private static LoginException createChainedLoginException(String msg, Exception e) {
        LoginException le = new LoginException(msg);
        le.initCause(e);
        return le;
    }
}
